import re
import os
import sys

''' 定义函数parse：解析文本，统计单词的出现频率 '''
# 该函数用于解析给定的文本，统计单词的出现频率，并返回按频率排序的单词列表
# 参数 text: 需要解析的文本字符串
# 返回值: 一个列表，其中包含按出现频率排序的单词和对应的次数
def parse(text):
    # 检查输入是否为字符串类型，如果不是字符串则抛出一个 ValueError 异常
    if not isinstance(text, str):
        raise ValueError("Input must be a string")
    
    # 使用正则表达式库 re 中的 sub 函数，将文本中的所有非字母数字字符（如标点符号和换行符）替换为空格
    # r'\W+' 是一个正则表达式模式，匹配一个或多个非字母数字字符
    text = re.sub(r'\W+', ' ', text)

    # 将文本转换为小写，以确保统计时不区分大小写
    # 例如，"Hello" 和 "hello" 会被视为同一个单词
    text = text.lower()
    
    # 使用 split 方法将文本按空格分割成单词列表
    # 例如，"hello world" 会被分割成 ["hello", "world"]
    word_list = text.split(' ')
    
    # 使用 filter 函数去除列表中的空白单词（即空字符串）
    # filter(None, word_list) 会过滤掉 word_list 中的所有假值（包括空字符串）
    word_list = filter(None, word_list)
    
    # 创建一个空字典，用于存储每个单词及其出现的次数
    word_cnt = {}
    # 遍历单词列表
    for word in word_list:
        # 如果单词不在字典中，则将其添加到字典，并将计数初始化为 0
        if word not in word_cnt:
            word_cnt[word] = 0
        # 将单词的计数加 1
        word_cnt[word] += 1
    
    # 使用 sorted 函数对字典中的项按词频进行排序
    # key=lambda kv: kv[1] 表示按字典项的值（即词频）进行排序
    # reverse=True 表示按降序排序，即词频高的单词排在前面
    sorted_word_cnt = sorted(word_cnt.items(), key=lambda kv: kv[1], reverse=True)
    
    # 返回按词频排序后的单词和词频列表
    return sorted_word_cnt

''' 解决运行脚本时，当前工作目录不是脚本所在目录的问题,无法用相对路径访问in.txt文件 '''
# 获取脚本所在的目录
script_dir = os.path.dirname(os.path.abspath(sys.argv[0]))
# 切换到脚本所在的目录
os.chdir(script_dir)
# 打印当前工作目录
print("Current working directory:", os.getcwd())

''' 读取文件内容 '''
# 打开文件 'in.txt' 以读取模式 ('r')，有 with 语句，就不需要显式调用 close()
with open('files/in.txt', 'r') as fin:
    # 读取文件的全部内容并存储在变量 text 中
    text = fin.read()

# 打印读取的文本内容
print("text", text)

# 调用 parse 函数解析文本，并将结果存储在 word_and_freq 变量中
word_and_freq = parse(text)

# 打印解析后的单词及其频率
print("word_and_freq", word_and_freq)

''' 写入文件 '''
# 打开文件 'out.txt' 以写入模式 ('w')
with open('files/out.txt', 'w') as fout:
    # 遍历 word_and_freq 列表中的每个单词及其频率
    for word, freq in word_and_freq:
        # 将单词和频率写入文件，格式为 "单词 频率"
        fout.write('{} {}\n'.format(word, freq))